﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Kyoh.App.Renamer.RenameEventArgs;
using Kyoh.Lib.WinForms;
using System.Globalization;
using System.Collections.Generic;
using System.Text;

namespace Kyoh.App.Renamer
{
    partial class MainForm : FormPlus
    {
        private bool _loaded;

        private RenamerArgument _args = null;

        public MainForm()
            : base(Properties.Settings.Default)
        {
            InitializeComponent();
            dataGridViewFiles.AutoGenerateColumns = false;
            dataGridViewFiles.DataSource = renameWorker;
        }

        public MainForm(RenamerArgument args)
            : this()
        {
            _args = args;
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            SaveConfig();
            base.OnFormClosing(e);
        }

        protected override void OnFormClosed(FormClosedEventArgs e)
        {
            Properties.Settings.Default.Save();
            base.OnFormClosed(e);
        }

        protected override void OnLoad(EventArgs e)
        {
            LoadConfig();

            _loaded = true;
            Listup();

            if (_args != null && _args.Run)
                Rename();

            base.OnLoad(e);
        }

        private void DataGridViewFilesCellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            if (!renameWorker.IsRenamed(e.RowIndex))
            {
                e.CellStyle.SelectionForeColor = Color.SkyBlue;
                e.CellStyle.ForeColor = Color.Silver;
            }
        }

        private void ButtonRenameClick(object sender, EventArgs e)
        {
            Rename();
        }

        private void RenameTreeListupProgress(object sender, ListupProgressChangedEventArgs e)
        {
            try { Invoke(new Action<string>(SetCurrentPath), e.CurrentPath); }
            catch { }
        }

        private void DataGridViewFilesColumnDividerDoubleClick(object sender, DataGridViewColumnDividerDoubleClickEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                dataGridViewFiles.AutoResizeColumn(e.ColumnIndex, DataGridViewAutoSizeColumnMode.DisplayedCells);
            e.Handled = true;
        }

        private void RenameTreeListupCompleted(object sender, CompletedEventArgs e)
        {
            try
            {
                Invoke(new Action(ResetCurrentPath));
                if (!e.Canceled)
                {

                    if (IsDirectoryRooted(fileSystemWatcher.Path))
                        fileSystemWatcher.EnableRaisingEvents = true;
                }
            }
            catch (Exception exc)
            {
                Debug.WriteLine(exc);
            }
        }

        private bool IsDirectoryRooted(string path)
        {
            return Path.IsPathRooted(path) && Directory.Exists(path);
        }

        private void FilterChanged(object sender, EventArgs e)
        {
            Listup();
        }

        private void Reload(object sender, EventArgs e)
        {
            Listup();
        }

        private void contextMenuStripFiles_Opening(object sender, CancelEventArgs e)
        {
            e.Cancel = true;
            var menu = new ShellContextMenu();

            menu.ShowContextMenu(
                dataGridViewFiles
                .SelectedRows
                .OfType<DataGridViewRow>()
                .Select(r => renameWorker.GetFullName(r.Index))
                .Where(s => s != null)
                .Select(s => new FileInfo(s))
                .ToArray()
                , Cursor.Position);
        }

        private void SetItemsCount(int count)
        {
            toolStripStatusLabelItemsCount.Text = count.ToString(CultureInfo.InvariantCulture);
        }

        private void SetCurrentPath(string path)
        {
            toolStripStatusLabelCurrentPath.Text = path;
            toolStripStatusLabelCurrentPath.Visible =
            toolStripStatusLabelCurrentPathCaption.Visible = !string.IsNullOrEmpty(path);
        }

        private void Listup()
        {
            if (!_loaded)
                return;
            Validate();
            Debug.WriteLine(dataGridViewFiles.IsCurrentRowDirty);
            fileSystemWatcher.EnableRaisingEvents = false;
            if (IsDirectoryRooted(renameOptionControl1.Path))
                fileSystemWatcher.Path = renameOptionControl1.Path;
            renameWorker.Listup(renameOptionControl1.GetOptions());
        }

        private void Rename()
        {
            Validate();
            Debug.WriteLine(dataGridViewFiles.IsCurrentRowDirty);
            dataGridViewFiles.EndEdit();
            if (renameWorker.GetFilteredCount() > 0)
                WorkingDialog.ShowDialog(this, renameWorker);
        }

        private void ResetCurrentPath()
        {
            toolStripStatusLabelCurrentPath.Visible =
                toolStripStatusLabelCurrentPathCaption.Visible = false;
        }

        internal void LoadConfig()
        {
            // PathHistory
            renameOptionControl1.LoadConfig(_args);

            // Show All
            toolStripButtonShowAllItems.Checked = Properties.Settings.Default.ShowAllItems;

            if (Properties.Settings.Default.DataGridViewFilesProfile != null)
                Properties.Settings.Default.DataGridViewFilesProfile.SetProfile(dataGridViewFiles);

        }

        internal void SaveConfig()
        {
            renameOptionControl1.SaveConfig();

            // Show All
            Properties.Settings.Default.ShowAllItems = toolStripButtonShowAllItems.Checked;

            if (Properties.Settings.Default.DataGridViewFilesProfile != null)
                Properties.Settings.Default.DataGridViewFilesProfile.GetProfile(dataGridViewFiles);
            else
                Properties.Settings.Default.DataGridViewFilesProfile = new DataGridViewColumnProfiles(dataGridViewFiles);
            Properties.Settings.Default.Save();
        }

        private void renameWorker_CountChanged(object sender, CountChangedEventArgs e)
        {
            SetItemsCount(renameWorker.Count);
        }

        private void toolStripButtonShowAllItems_CheckedChanged(object sender, EventArgs e)
        {
            var check = sender as ToolStripButton;
            if (check == null)
                return;
            if (check.Checked)
                renameWorker.Filter = "Renamed";
            else
                renameWorker.RemoveFilter();
        }

        private void toolStripButtonHelp_Click(object sender, EventArgs e)
        {
            using (var aboutBox = new RenamerAboutBox())
                aboutBox.ShowDialog();
        }

        private void MainForm_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop) && e.AllowedEffect.HasFlag(DragDropEffects.Copy))
                e.Effect = DragDropEffects.Copy;
        }

        private void MainForm_DragDrop(object sender, DragEventArgs e)
        {
            var files = e.Data.GetData(DataFormats.FileDrop) as string[];
            if (files == null || files.Length < 1)
                return;
            if (Directory.Exists(files[0]))
                BeginInvoke(new Action(() => { renameOptionControl1.Path = files[0]; }));
            else if (File.Exists(files[0]))
                BeginInvoke(new Action(() => { renameOptionControl1.Path = Path.GetDirectoryName(files[0]); }));
        }

        private void renameQueueManagerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            renameOptionControl1.OpenQueueManagerDialog();
        }

        private void removeRenameToolStripMenuItem_Click(object sender, EventArgs e)
        {
            renameOptionControl1.RemoveOption();
        }

        private void clearRenamesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            renameOptionControl1.ClearOptions();
        }

        private void saveABatchToolStripMenuItem_Click(object sender, EventArgs e)
        {
            renameOptionControl1.SaveBatch();
        }

        private void loadABatchToolStripMenuItem_Click(object sender, EventArgs e)
        {
            renameOptionControl1.LoadBatch();
        }

        private void setATargetToolStripMenuItem_Click(object sender, EventArgs e)
        {
            renameOptionControl1.SelectTarget();
        }

        private void eXitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void queueToolStripMenuItem_DropDownClosed(object sender, EventArgs e)
        {
        }

            const string QueueMenuItemNamePrefix = "QueueMenuItem";
            const string QueueMenuItemTopNamePrefix = "QueueMenuItemMoveTop";
            const string QueueMenuItemUpNamePrefix = "QueueMenuItemMoveUp";
            const string QueueMenuItemDownNamePrefix = "QueueMenuItemMoveDown";
            const string QueueMenuItemBottomNamePrefix = "QueueMenuItemMoveBottom";

        private void queueToolStripMenuItem_DropDownOpening(object sender, EventArgs e)
        {
            var menu = queueToolStripMenuItem;
            var batch = renameOptionControl1.GetOptions();
            
            string itemKey, itemTopKey, itemUpKey, itemDownKey, itemBottomKey;
            ToolStripIndexedMenuItem menuItem;
            int index = 0, count = batch.Count;
            foreach (var entry in batch)
            {
                itemKey = QueueMenuItemNamePrefix + index;
                itemTopKey = QueueMenuItemTopNamePrefix + index;
                itemUpKey = QueueMenuItemUpNamePrefix + index;
                itemDownKey = QueueMenuItemDownNamePrefix + index;
                itemBottomKey = QueueMenuItemBottomNamePrefix + index;

                if (menu.DropDownItems.ContainsKey(itemKey))
                    menuItem = (ToolStripIndexedMenuItem)menu.DropDownItems[itemKey];
                else
                {
                    menuItem = new ToolStripIndexedMenuItem(
                        string.Empty,
                        new ToolStripMenuItem(Properties.TextResources.MoveTop, Properties.Resources.bullet_arrow_top_16, MoveToTopEntry) { Tag = index, Name = itemTopKey },
                        new ToolStripMenuItem(Properties.TextResources.MoveUp, Properties.Resources.bullet_arrow_up_16, MoveUpEntry) { Tag = index, Name = itemUpKey },
                        new ToolStripMenuItem(Properties.TextResources.Select, Properties.Resources.check_box_16, SelectEntry) { Tag = index },
                        new ToolStripMenuItem(Properties.TextResources.MoveDown, Properties.Resources.bullet_arrow_down_16, MoveDownEntry) { Tag = index, Name = itemDownKey },
                        new ToolStripMenuItem(Properties.TextResources.MoveBottom, Properties.Resources.bullet_arrow_bottom_16, MoveToBottomEntry) { Tag = index, Name = itemBottomKey }
                    );
                    menuItem.Name = itemKey;
                    menuItem.Index = index;
                    menu.DropDownItems.Add(menuItem);
                }
                menuItem.Text = (string.IsNullOrWhiteSpace(entry.Pattern) && string.IsNullOrWhiteSpace(entry.Replacement) ? "(empty)" : entry.Pattern + " => " + entry.Replacement);
                menuItem.Checked = renameOptionControl1.SelectedIndex == index;
                menuItem.DropDownItems[itemTopKey].Enabled = index > 0;
                menuItem.DropDownItems[itemUpKey].Enabled = index > 0;
                menuItem.DropDownItems[itemDownKey].Enabled = index < count - 1;
                menuItem.DropDownItems[itemBottomKey].Enabled = index < count - 1;

                index++;
            }

            while (menu.DropDownItems.ContainsKey(itemKey = QueueMenuItemNamePrefix + (index++)))
                menu.DropDownItems.RemoveByKey(itemKey);
        }

        private void SelectEntry(object sender, EventArgs e)
        {
            var index = GetEntryIndex(sender);
            if (index >= 0)
                renameOptionControl1.SelectQueue(true, index);
        }

        private int GetEntryIndex(object sender)
        {
            var menuItem = sender as ToolStripMenuItem;
            return menuItem == null || !(menuItem.Tag is int) ? -1 : (int)menuItem.Tag;
        }

        private void Shift(int i, int p)
        {
            renameOptionControl1.ShiftOption(i, p);
        }

        private void MoveToTopEntry(object sender, EventArgs e)
        {
            var index = GetEntryIndex(sender);
            Shift(index, 0);
        }

        private void MoveUpEntry(object sender, EventArgs e)
        {
            var index = GetEntryIndex(sender);
            Shift(index, index - 1);
        }

        private void MoveDownEntry(object sender, EventArgs e)
        {
            var index = GetEntryIndex(sender);
            Shift(index, index + 1);
        }

        private void MoveToBottomEntry(object sender, EventArgs e)
        {
            var index = GetEntryIndex(sender);
            Shift(index, -1);
        }

        private void wildcardToolStripMenuItem_Click(object sender, EventArgs e)
        {
            renameOptionControl1.AddNewOption(PatternMethod.Wildcard);
        }

        private void regexToolStripMenuItem_Click(object sender, EventArgs e)
        {
            renameOptionControl1.AddNewOption(PatternMethod.Regex);
        }

        private void characteristicToolStripMenuItem_Click(object sender, EventArgs e)
        {
            renameOptionControl1.AddNewOption(PatternMethod.Characteristic);
        }

        private void toolStripButtonRemoveUserSupplements_Click(object sender, EventArgs e)
        {
            RenameEntryCollection.IndexReplacer index = new RenameEntryCollection.IndexReplacer();
            foreach (DataGridViewRow row in dataGridViewFiles.SelectedRows)
            {
                index.Index = row.Index;
                renameWorker.RemoveUserSupplement(index, row.DataBoundItem);
                dataGridViewFiles.UpdateCellValue(0, row.Index);
                dataGridViewFiles.UpdateCellValue(2, row.Index);
            }
        }

        private void dataGridViewFiles_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {

        }

        private void buttonUndo_Click(object sender, EventArgs e)
        {
            renameWorker.Undo();
        }

        private void showPreferencesClick(object sender, EventArgs e)
        {
            using (var pref = new PreferencesForm())
                pref.ShowDialog();
        }

    }
}